package com.lcf.framework.utils;

import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.lcf.common.enums.DictTypeEnum;
import com.lcf.feign.service.system.SysDictFeignService;
import com.lcf.framework.config.IsDictServiceConfig;
import com.lcf.framework.enums.SysDictStatusEnum;
import com.lcf.framework.model.system.SysDict;
import com.lcf.framework.model.system.SysDictType;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 描述：字典
 *
 * @author lcf
 * @since 2025/3/30 15:15
 */
@Component
public class DictUtils {
    @Resource
    private IsDictServiceConfig isDictService;
    @Resource
    private SysDictFeignService sysDictFeignService;

    /**
     * 缓存字典值 typeCode -> dictCode -> dictName
     */
    private final ThreadLocal<LoadingCache<String, Map<String, String>>> dictCache = ThreadLocal.withInitial(() ->
            Caffeine.newBuilder()
                    .build(typeCode -> {
                        Map<String, String> data = getByTypeCode(typeCode);
                        // 用空Map占位防止缓存穿透
                        return data != null ? data : Collections.emptyMap();
                    })
    );

    /**
     * 获取字典名称（自动防击穿：同一 key 并发请求只有一个线程加载）
     */
    public String getDictName(DictTypeEnum dictType, String dictValue) {
        return Optional.ofNullable(getCache().get(dictType.getTypeCode())).map(map -> map.get(dictValue)).orElse(null);
    }

    /**
     * 从数据库加载字典数据
     */
    public Map<String, String> getByTypeCode(String typeCode) {
        if (Objects.equals(isDictService.getIsDictService(), true)) {
            SysDictType dictType = Db.lambdaQuery(SysDictType.class)
                    .eq(SysDictType::getTypeCode, typeCode)
                    .one();
            if (dictType == null) {
                return null;
            }

            Map<String, String> data = Db.lambdaQuery(SysDict.class)
                    .eq(SysDict::getTypeId, dictType.getId())
                    .eq(SysDict::getStatus, SysDictStatusEnum.ENABLE.getCode())
                    .list().stream()
                    .collect(Collectors.toMap(SysDict::getDictValue, SysDict::getDictName));

            return Collections.unmodifiableMap(data);
        }

        return sysDictFeignService.getByTypeCode(typeCode);
    }

    /**
     * 获取当前请求缓存实例
     */
    private LoadingCache<String, Map<String, String>> getCache() {
        return dictCache.get();
    }

    /**
     * 清空缓存
     */
    public void clearCache() {
        getCache().invalidateAll();
        dictCache.remove();
    }
}
